{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Import SolidPython and viewscad:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from solid import *\n",
    "import viewscad\n",
    "\n",
    "r = viewscad.Renderer()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's create an object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f0bb7e263ada46b0affc56b795d96880",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HTML(value=''), Renderer(background='#cccc88', background_opacity=0.0, camera=PerspectiveCamera…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "c = cylinder(r=5, h=2)\n",
    "c -= minkowski() (translate([0, 0, 1]) (cylinder(r=3, h=1.5)), sphere(r=0.2))\n",
    "c -= cylinder(r=1, h=3, center=True)\n",
    "c -= translate([0, -1, 0]) (cube([6, 2, 3]))\n",
    "r.render(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The renderer can also render raw OpenSCAD code, and save objects to .STL files:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "scad_code = '''\n",
    "union() {\n",
    "    cube([1,1,10]);\n",
    "    sphere(r=2);\n",
    "}\n",
    "'''\n",
    "r.render(scad_code, outfile='tmp.stl')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A more complex object: a Sierpinski tetrahedron:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "dcf207241ad64e1a9bfec1180e5c3256",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HTML(value=''), Renderer(background='#cccc88', background_opacity=0.0, camera=PerspectiveCamera…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "points=np.array([[0,0,0], [1,0,0],[0.5,0.5*np.sqrt(3), 0], [0.5, 0.5/np.sqrt(3), np.sqrt(2./3)]])\n",
    "def tetra():\n",
    "    return polyhedron(points=points, faces=[[0,1,2], [0,3,1], [0,2,3], [1,3,2]])\n",
    "\n",
    "def sierpinski(depth, size):\n",
    "    if depth == 0:\n",
    "        return scale(size) (tetra())\n",
    "    else:\n",
    "        obj = None\n",
    "        for point in points:\n",
    "            o = translate(size/2*point) (sierpinski(depth-1, size/2))\n",
    "            if obj is None: obj = o\n",
    "            else: obj += o\n",
    "        \n",
    "        return obj\n",
    "    \n",
    "r.render(sierpinski(3, 1.))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introspection\n",
    "Let's create a tetrahedron with rounded edges:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "c72941f2d8374e05a974b08725b88abc",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HTML(value=''), Renderer(background='#cccc88', background_opacity=0.0, camera=PerspectiveCamera…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "t = hull() (sum([translate(x) (sphere(r=1.0)) for x in [[0,0,0], [20, 0, 0], [0, 20, 0], [0, 0, 30]]]))\n",
    "r.render(t)\n",
    "         "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But say we want the big face to be downwards.  We could of course do some trigonometry, but we can also just double-click on the big face, where we learn the face index, which in my case was 4 (but could be different for you).  We can then create a new object with this face rotated downwards:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "7600c71899744479880e002e17e3b9ed",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HTML(value=''), Renderer(background='#cccc88', background_opacity=0.0, camera=PerspectiveCamera…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "t2 = r.rotate_face_down(t, 4) (t)\n",
    "r.render(t2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's say we had a cone which we wanted to emerge from one of the sides of t2, our new object. We can do this with the `Renderer.place_on()` method:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "110244a980eb42829bc90f4f82916a7c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HTML(value=''), Renderer(background='#cccc88', background_opacity=0.0, camera=PerspectiveCamera…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "cone = cylinder(h=15., r1=4.0, r2=0.0)\n",
    "r.render(cone)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3a22ba035c3b41f8b97185b15feaf721",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HTML(value=''), Renderer(background='#cccc88', background_opacity=0.0, camera=PerspectiveCamera…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "new_obj = r.place_on(cone, t2, align_face1=28, align_face2=25, point1=r.get_face_centroid(cone, 28), point2=r.get_face_centroid(t2, 25))\n",
    "r.render(new_obj)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
